package com.KOL.model;

import com.KOL.model.character.PlayerCharacter;
import com.KOL.model.items.DroppedItem;
import com.KOL.model.items.Item;
import com.KOL.model.items.ItemType;
import com.KOL.present.TileType;
import java.awt.*;
import java.util.*;
import java.awt.image.*;


public class WorldItems {
  private int tileWidth, tileHeight;
  private int evenRowX, evenRowY;
  private int oddRowX, oddRowY;

  private ArrayList<TileOccupier> items; // a row-ordered list of TileOccupier objects


  public WorldItems(int w, int h, int erX, int erY,
                                  int orX, int orY) {
    tileWidth = w; tileHeight = h;
    evenRowX = erX; evenRowY = erY;
    oddRowX = orX; oddRowY = orY;
    items = new ArrayList();
  }

  public void addObsticalItem(String name, TileType type, int x, int y, BufferedImage im) {
    TileOccupier toc;
    if (y%2 == 0) // even row
      toc = new TileOccupier(name, type, x, y, im,
                                    evenRowX, evenRowY,
                                    tileWidth, tileHeight);
    else
      toc = new TileOccupier(name, type, x, y, im,
                                    oddRowX, oddRowY,
                                    tileWidth, tileHeight);
    rowInsert(toc, x, y);
  }

  public void addDroppedItem(Item item,String name, int x, int y, BufferedImage im) {
    DroppedItem droppedItem;
    if (y%2 == 0) // even row
      droppedItem = new DroppedItem(item,name, TileType.ITEM, x, y, im,
                                    evenRowX, evenRowY,
                                    tileWidth, tileHeight);
    else
      droppedItem = new DroppedItem(item, name, TileType.ITEM, x, y, im,
                                    oddRowX, oddRowY,
                                    tileWidth, tileHeight);
    rowInsert(droppedItem, x, y);
  }

  private void rowInsert(TileOccupier toc, int x, int y) {
    TileOccupier item;
    Point itemPt;
    int i = 0;
    while(i < items.size()) {
      item = (TileOccupier) items.get(i);
      itemPt = item.getTileLoc();
      if (y < itemPt.y)
        break;
      else if ((y == itemPt.y) && (x < itemPt.x))
        break;
      i++;
    }
    items.add(i, toc);
  }

  public void draw(Graphics g, int xOffset, int yOffset) {
    for(TileOccupier item : items) {
        item.draw(g, xOffset, yOffset);
    }
  } 

  public void positionSprites(PlayerCharacter pc, Enemy[] enemies) {
    posnEntity(pc.getName(), pc);

    for(Enemy enemy : enemies) {
        posnEntity("" + enemy.getEnemyID(),enemy);
    }
  }

  private void posnEntity(String name, TiledEntity tEntity) {
    Point sPt = tEntity.getTileLoc();

    TileOccupier toc;
    if (sPt.y%2 == 0) // even row
      toc = new TileOccupier(name, TileType.ENTITY,
                                    sPt.x, sPt.y, tEntity.getImage(),
                                    evenRowX, evenRowY,
                                    tileWidth, tileHeight);
    else
      toc = new TileOccupier(name, TileType.ENTITY,
                                    sPt.x, sPt.y, tEntity.getImage(),
                                    oddRowX, oddRowY,
                                    tileWidth, tileHeight);

    toc.addEntityRef(tEntity);
    rowInsert(toc, sPt.x, sPt.y);
  }

  public void removeEntity() {
    TileOccupier item;
    int i = 0;
    while(i < items.size()) {
      item = (TileOccupier) items.get(i);
      if (item.getType() == TileType.ENTITY)
        items.remove(i);
      else
        i++;
    }
  }

  public String findItemName(Point pt) {
    TileOccupier item;
    for(int i=0; i < items.size(); i++) {
      item = (TileOccupier) items.get(i);
      if ((item.getType() == TileType.ITEM) &&
          (pt.equals( item.getTileLoc())))
        return item.getName();
    }
    return null;
  }

  public Point nearestItem(Point pt) {
    double minDist = Integer.MAX_VALUE;
    Point minPoint = null;
    double dist;
    TileOccupier item;
    for(int i=0; i < items.size(); i++) {
      item = (TileOccupier) items.get(i);
      if (item.getType() == TileType.ITEM) {
        dist = pt.distanceSq( item.getTileLoc() );
        if (dist < minDist) {
          minDist = dist;                
          minPoint = item.getTileLoc();
        }
      }
    }
    return minPoint;
  }

  public boolean removeItem(String name) {
    TileOccupier item;
    for(int i=0; i < items.size(); i++) {
      item = items.get(i);
      if ((item.getType() == TileType.ITEM) &&
          (name.equals(item.getName()))) { 
        items.remove(i);
        return true;
      }
    }
    return false;
  }

    public Item getItem(String name) {
        Item item = null;

        for (TileOccupier toc : items) {
            if(toc.getName().equals(name)) {
                if(toc instanceof DroppedItem)
                    item = ((DroppedItem)(toc)).getItem();
            }
        }

        return item;
    }
}


